package com.javandad.app.client.chat;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.cellview.client.CellList;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.DecoratorPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;
import com.javandad.app.client.AsyncCallback;
import com.javandad.app.client.cells.UserCell;
import com.javandad.app.shared.entity.ChatMessage;
import com.javandad.app.shared.entity.User;

public class Chat implements EntryPoint {

	private final ChatServiceAsync chatService = GWT.create(ChatService.class);
	
	private List<User> on = new ArrayList<User>();
	private Map<String, ChatWindow> chatWindows = new HashMap<String, ChatWindow>();
	private final CellList<User> online = new CellList<User>(new UserCell());

	@Override
	public void onModuleLoad() {
		RootPanel root = RootPanel.get("chatContainer");
		initGui(root);
		
		Timer presenceUpdater = new Timer() {
			@Override
			public void run() {
				updatePresence();
			}};
		presenceUpdater.scheduleRepeating(5*1000);
		updatePresence();
		
		final Timer poller = new Timer() {
			@Override
			public void run() {
				poll();
			}};
		Timer delay = new Timer()
		{
			@Override
			public void run() {
				poller.scheduleRepeating(1*1000);
			}
		};
		delay.schedule(500);
	}

	private void initGui(RootPanel root) {
		DecoratorPanel chatpanel = new DecoratorPanel();
		chatpanel.setSize("100%", "10px");
		VerticalPanel foo = new VerticalPanel();
		final SingleSelectionModel<User> selectionModel = new SingleSelectionModel<User>();
		online.setSelectionModel(selectionModel);
		selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
			public void onSelectionChange(SelectionChangeEvent event) {
				User user = selectionModel.getSelectedObject();
				openChatWindow(user);
			}
		});
		//foo.add(new HTML("JaVandad Chat:<br><hr style='width:100%;' />"));
		foo.add(online);
		foo.setWidth("100%");
		chatpanel.add(foo);
		root.add(chatpanel);
	}

	private ChatWindow openChatWindow(User partner)
	{
		ChatWindow cw = chatWindows.get(partner.getUserId());
		if(cw == null)
		{
			cw = new ChatWindow(partner, chatService);
			chatWindows.put(partner.getUserId(), cw);
		}
		cw.show();
		return cw;
	}
	
	private void updatePresence()
	{
		chatService.whosOnline(new AsyncCallback<List<User>>() {
			@Override
			public void onSuccess(List<User> result) {
				List<User> wentOff = Chat.diff(on, result);
				wentOff(wentOff);
				List<User> wentOn = Chat.diff(result, on);
				wentOn(wentOn);
				on = result;
				online.setRowData(on);
			}});
	}
	private void wentOn(List<User> wentOn)
	{
		
	}
	private void wentOff(List<User> wentOff)
	{
		
	}
	
	private void poll()
	{
		chatService.poll(new AsyncCallback<List<ChatMessage>>() {
			@Override
			public void onSuccess(List<ChatMessage> result) {
				if(result == null)
					return;
				for(ChatMessage m : result)
				{
					ChatWindow cw = openChatWindow(m.sender);
					cw.newMessage(m);
				}
			}});
	}
	
	public static <T> List<T> diff(List<T> a, List<T> b)
	{
		List<T> diff = new ArrayList<T>();
		for(T t : a)
			if(!b.contains(t))
				diff.add(t);
		return diff;
	}
	
}
